package com.sxkj.gis.wms.bean;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageReadParam;

import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.geotools.coverage.grid.io.imageio.GeoToolsReadParams;
import org.geotools.data.FeatureSource;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.Layer;
import org.geotools.map.MapContent;
import org.geotools.map.MapViewport;
import org.geotools.referencing.CRS;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.PNGEncodeParam;
import com.sxkj.gis.wms.process.WmsProProcess;

/**
 * 对GetMapParams中参数进行处理 的类
 * @author admin
 *
 */
public class DoWmsParams implements WmsProProcess {
	
	private String version;
	
	private String request;
	
	private Double[] bbox;
	
	private Integer width;
	
	private Integer Height;
	
	private List<SimpleFeatureSource> simpleFeatureSources;
	
	private List<Style> styles;
	
	private String Format;
	
	private String srs;

	private String info_format;
	
	private Integer x;
	
	private Integer y;
	
	private List<SimpleFeatureSource> querylayerssimpleFeatureSources;
	
	public String getInfo_format() {
		return info_format;
	}

	public void setInfo_format(String info_format) {
		this.info_format = info_format;
	}

	public Integer getX() {
		return x;
	}

	public void setX(Integer x) {
		this.x = x;
	}

	public Integer getY() {
		return y;
	}

	public void setY(Integer y) {
		this.y = y;
	}

	public List<SimpleFeatureSource> getQuerylayerssimpleFeatureSources() {
		return querylayerssimpleFeatureSources;
	}

	public void setQuerylayerssimpleFeatureSources(List<SimpleFeatureSource> querylayerssimpleFeatureSources) {
		this.querylayerssimpleFeatureSources = querylayerssimpleFeatureSources;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public String getRequest() {
		return request;
	}

	public void setRequest(String request) {
		this.request = request;
	}

	public Double[] getBbox() {
		return bbox;
	}

	public void setBbox(Double[] bbox) {
		this.bbox = bbox;
	}

	public Integer getWidth() {
		return width;
	}

	public void setWidth(Integer width) {
		this.width = width;
	}

	public Integer getHeight() {
		return Height;
	}

	public void setHeight(Integer height) {
		Height = height;
	}

	public List<SimpleFeatureSource> getSimpleFeatureSources() {
		return simpleFeatureSources;
	}

	public void setSimpleFeatureSources(List<SimpleFeatureSource> simpleFeatureSources) {
		this.simpleFeatureSources = simpleFeatureSources;
	}

	public List<Style> getStyles() {
		return styles;
	}

	public void setStyles(List<Style> styles) {
		this.styles = styles;
	}

	public String getFormat() {
		return Format;
	}

	public void setFormat(String format) {
		Format = format;
	}

	public String getSrs() {
		return srs;
	}

	public void setSrs(String srs) {
		this.srs = srs;
	}

	public DoWmsParams() {
		super();
	}

	public DoWmsParams(String version, String request, Double[] bbox, Integer width, Integer height,
			List<SimpleFeatureSource> simpleFeatureSources, List<Style> styles, String format, String srs) {
		super();
		this.version = version;
		this.request = request;
		this.bbox = bbox;
		this.width = width;
		Height = height;
		this.simpleFeatureSources = simpleFeatureSources;
		this.styles = styles;
		Format = format;
		this.srs = srs;
	}
	
	

	public DoWmsParams(String version, String request, Double[] bbox, Integer width, Integer height,
			List<SimpleFeatureSource> simpleFeatureSources, List<Style> styles, String format, String srs,
			String info_format, Integer x, Integer y, List<SimpleFeatureSource> querylayerssimpleFeatureSources) {
		super();
		this.version = version;
		this.request = request;
		this.bbox = bbox;
		this.width = width;
		Height = height;
		this.simpleFeatureSources = simpleFeatureSources;
		this.styles = styles;
		Format = format;
		this.srs = srs;
		this.info_format = info_format;
		this.x = x;
		this.y = y;
		this.querylayerssimpleFeatureSources = querylayerssimpleFeatureSources;
	}
	/**
	 * 返回图片流
	 */
	@Override
	public Map<String,ByteArrayOutputStream> returnPictureByteStream() throws NoSuchAuthorityCodeException, FactoryException, IOException {
		Map<String,ByteArrayOutputStream> outMap = new HashMap<>();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			CoordinateReferenceSystem crs = CRS.decode(this.srs,true);
			ReferencedEnvelope mapArea = new ReferencedEnvelope(this.bbox[0], this.bbox[2], this.bbox[1], this.bbox[3], crs);
			
			//单个图层
			Layer layer = new FeatureLayer(this.simpleFeatureSources.get(0), this.styles.get(0));
			
			//初始化容器添加图层
			MapContent mapContent = new MapContent();
			
			MapViewport mp = new MapViewport();
			
			mp.setCoordinateReferenceSystem(crs);
			
			//mapContent.setViewport(mp);
			
			mapContent.layers().add(layer);
			
			StreamingRenderer sr = new StreamingRenderer();
			sr.setMapContent(mapContent);
			
			BufferedImage image = new BufferedImage(this.width,this.Height,BufferedImage.TYPE_INT_ARGB);
			
			Graphics g = image.getGraphics();
			
			((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			
			Rectangle rect = new Rectangle(0,0,this.width,this.Height);
			sr.paint((Graphics2D) g, rect, mapArea);
			
			
			PNGEncodeParam encodeParam = PNGEncodeParam.getDefaultEncodeParam(image);

			if (encodeParam instanceof PNGEncodeParam.Palette) {
				PNGEncodeParam.Palette p = (PNGEncodeParam.Palette) encodeParam;
				byte[] b = new byte[] { -127 };
				p.setPaletteTransparency(b);
			}
			com.sun.media.jai.codec.ImageEncoder encoder = ImageCodec.createImageEncoder("PNG", out, encodeParam);
			encoder.encode(image.getData(), image.getColorModel());
			outMap.put("byteArrayOutputStream", out);
			out.flush();
			out.close();
			return outMap;
	}
	
	/**
	 * 返回SVG 文件流
	 * @return 
	 * @return
	 * @throws FactoryException 
	 * @throws NoSuchAuthorityCodeException 
	 * @throws IOException 
	 */
	public Map<String,ByteArrayOutputStream> returnSVGByteStream(SVGGraphics2D svgGenerator) throws NoSuchAuthorityCodeException, FactoryException, IOException{
		Map<String,ByteArrayOutputStream> outMap = new HashMap<>();
		CoordinateReferenceSystem crs = CRS.decode(this.srs,true);
		ReferencedEnvelope mapArea = new ReferencedEnvelope(this.bbox[0], this.bbox[2], this.bbox[1], this.bbox[3], crs);
		
		//单个图层
		Layer layer = new FeatureLayer(this.simpleFeatureSources.get(0), this.styles.get(0));
		
		//初始化容器添加图层
		MapContent mapContent = new MapContent();
		
		MapViewport mp = new MapViewport();
		
		mp.setCoordinateReferenceSystem(crs);
		
		//mapContent.setViewport(mp);
		
		mapContent.layers().add(layer);
		
		StreamingRenderer sr = new StreamingRenderer();
		sr.setMapContent(mapContent);
		
		BufferedImage image = new BufferedImage(this.width,this.Height,BufferedImage.TYPE_INT_ARGB);
		
		Rectangle rect = new Rectangle(0,0,this.width,this.Height);
		sr.paint(svgGenerator, rect, mapArea);
		
		boolean useCSS = true; // we want to use CSS style attributes
		ByteArrayOutputStream byteout = new ByteArrayOutputStream();
	    Writer out = new OutputStreamWriter(byteout, "UTF-8");
	    svgGenerator.stream(out, useCSS);
	    outMap.put("SVG", byteout);
	    out.flush();
	    out.close();
	    return outMap;
	}
	
	/**
	 * 构建SVGGenerator
	 */
	public static SVGGraphics2D  getSVGGenerator(){
		  // Get a DOMImplementation.
	    DOMImplementation domImpl =
	      GenericDOMImplementation.getDOMImplementation();

	    // Create an instance of org.w3c.dom.Document.
	    String svgNS = "http://www.w3.org/2000/svg";
	    Document document = domImpl.createDocument(svgNS, "svg", null);

	    // Create an instance of the SVG Generator.
	    SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
	    return svgGenerator;
	}
	
	/**
	 * FeatureInfo请求
	 * @return
	 * @throws FactoryException 
	 * @throws NoSuchAuthorityCodeException 
	 * @throws IOException 
	 */
	public  Map<String,byte[]> getFeatureInfoRequest() throws NoSuchAuthorityCodeException, FactoryException, IOException{
		Map<String,byte[]> outMap = new HashMap<>();
		double x1,y1,x2,y2;
		int width,height,i,j;
		x1 = this.bbox[0];
		y1 = this.bbox[1];
		x2 = this.bbox[2];
		y2 = this.bbox[3];
		
		width =this.width;
		height = this.Height;
		
		i = this.x;
		j = this.y;
		
		//计算点选范围的地图坐标
		double cx1, cy1, cx2, cy2;
		cx1 = x1 * (width - i + 0.5 ) / width + x2* (i - 0.5 ) / width;
        cx2 = x1 * (width - i + 0.5 ) / width + x2* (i - 0.5 ) / width;
        cy1 = y1 * (j - 0.5) / height + y2* (height - j + 0.5 ) / height;
        cy2 = y1 * (j - 0.5) / height + y2 * (height - j + 0.5) / height;
        
        CoordinateReferenceSystem crs = CRS.decode(this.srs,true);
        ReferencedEnvelope clickArea = new ReferencedEnvelope(cx1, cx2, cy1, cy2, crs);
        SimpleFeatureSource featureSource = this.getSimpleFeatureSources().get(0);
        //因为不是所有的实现都要使用geoapi几何。这允许使用sfsql几何complient过滤器创建构建。认为这是一个桥梁，让geoapi用于现有项目
        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
        String geometryPropertyName = featureSource.getSchema().getGeometryDescriptor().getLocalName();    
        Filter filter = ff.bbox(ff.property(geometryPropertyName), clickArea);
        FeatureCollection fc = featureSource.getFeatures(filter);
        SimpleFeatureType schema = (SimpleFeatureType) fc.getSchema();
        FeatureIterator fi = fc.features();
        String text = null;
        
        if (fi.hasNext()) {
           text = "Selected feature(s) in layer ["+schema.getTypeName()+"]\n";
           text+="---------------------------------------\n";
            while (fi.hasNext()) {
                SimpleFeature f = (SimpleFeature) fi.next();
                text += "id=" + f.getID()+"\n";
                for (AttributeDescriptor type : schema
                        .getAttributeDescriptors()) {
                    String name = type.getLocalName();
                    if (!name.equals(geometryPropertyName))
                   text +=	name + "=" + f.getProperty(name).getValue().toString()+"\n";
                                
                }
            }
        }
        text+="---------------------------------------\n";
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buff = text.getBytes();
        outMap.put("textStream", buff);
        out.flush();
        out.close();
		return outMap;
	}
	
	
}
